package com.lucaswangdev.logindemo.aspect;

import com.alibaba.fastjson.JSON;
import com.lucaswangdev.logindemo.constant.common.ErrorConstants;
import com.lucaswangdev.logindemo.exception.BusinessException;
import com.lucaswangdev.logindemo.web.BaseResult;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Arrays;

@Component
@Aspect
public class CommonAspect {

    private static final Logger logger = LoggerFactory.getLogger(CommonAspect.class);

    @Around("execution(public * com.lucaswangdev.life.operating.system.web.controller..*.*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String classMethodName = signature.getDeclaringType().getSimpleName() + "#" + signature.getMethod().getName();
        // Filter arguments to avoid serializing HttpServletRequest and similar types
        Object[] filteredArgs = filterArgs(joinPoint.getArgs());
        try {
            logger.error(classMethodName + ",------request------:" + JSON.toJSONString(filteredArgs));
            Object result = joinPoint.proceed();
            logger.error(classMethodName + ",------response------:" + JSON.toJSONString(result));
            return result;
        } catch (BusinessException businessException) {
            logger.error(classMethodName + ",------businessException------:" + businessException.toString(), businessException);
            return BaseResult.bizFail(businessException);
        } catch (Throwable throwable){
            logger.error(classMethodName + ",------throwable------:" + throwable.getMessage(), throwable);
            return BaseResult.bizFail(ErrorConstants.SYSTEM_ERROR.getErrorCode(), throwable.getMessage());
        }
    }

    // Helper method to filter non-serializable arguments
    private Object[] filterArgs(Object[] args) {
        return Arrays.stream(args)
                .filter(arg -> !(arg instanceof HttpServletRequest || arg instanceof HttpServletResponse))
                .toArray();
    }
}
